package com.ug_project.adapters

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.ug_project.annotations.AvailableDefaultValue
import com.ug_project.objects.isNotNull
import com.ug_project.objects.isNull

/**
 * Created by Administrator on 2/19/2017.
 */

open class BaseAdapter<T>(val context: Context, val layout_res_id: Int, var data: ArrayList<T>) : android.widget.BaseAdapter()
{
    private var filterData = ArrayList<T>()
    private var _getView: ((position: Int,rootView: View, parent: ViewGroup?, data: ArrayList<T>) -> Unit)? = null
    private var _getViewForItemData: ((position: Int,rootView: View, parent: ViewGroup?, data: T) -> Unit)? = null
    private var _getItem: ((position: Int)-> Any)? = null
    private var _getItemId: ((position: Int) -> Long)? = null
    private var _getCount: (()-> Int)? = null
    private val _inflater: LayoutInflater
    private var filterAction: (T) -> Boolean = {true}


    init {
        _inflater = LayoutInflater.from(context)
        filterData.clear()
        filterData.addAll(data.filter { filterAction(it) })
    }

    open fun refresh(){
        filter(filterAction)
    }

    open fun GetItem(getitem: (position: Int)-> Any)
    {
        _getItem = getitem
    }

    @AvailableDefaultValue
    open fun GetItemId(getitemid: (position: Int) -> Long)
    {
        _getItemId = getitemid
    }

    open fun GetCount(getcount: ()-> Int)
    {
        _getCount = getcount
    }

    open fun GetView(getview: (position: Int,rootView: View, parent: ViewGroup?, data: ArrayList<T>) -> Unit)
    {
        _getView = getview
    }

    /**
     * Get View For Item Data
     */
    open fun GetViewIData(getview: (position: Int,rootView: View, parent: ViewGroup?, data: T) -> Unit)
    {
        _getViewForItemData = getview
    }

    fun filter(action: (T) -> Boolean)
    {
        filterAction = action
        filterData.clear()
        filterData.addAll(data.filter { filterAction(it) })
        notifyDataSetChanged()
    }

    override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {

//        _getView isNull {
//            _Exception("GetView(getview: (position: Int, inflatedViews: Array<View>, convertView: View?, parent: ViewGroup?) -> View)")
//        }

        val parent_view: View = convertView ?: try {
            _inflater.inflate(layout_res_id, null)
        } catch (exception: Exception) {
            throw Exception("پارامىتىر قىلىپ بەرگەن \n layout_res_id \n بولسا چوقۇم \n ViewGroup نىڭ ئۆزى ياكى بالىسى بولىشى كىرەك")
        }


        _getView?.invoke(position, parent_view, parent, filterData)
        _getViewForItemData?.invoke(position, parent_view, parent, filterData[position])

        return parent_view
    }

    override fun getItem(position: Int): Any {
        var item: Any? = null
        data.isNull {
            _getItem.isNull {
                _Exception("GetItem(getitem: (position: Int)-> Any)")
            }
            item = _getItem!!(position)
        }
        data isNotNull {
            item = it[position]
        }
        return item!!
    }

    override fun getItemId(position: Int): Long {
        var id = position
        _getItemId isNotNull {
            id = _getItemId!!(position).toInt()
        }
        return id.toLong()
    }

    override fun getCount(): Int {
        var count = -1
//        data.isNull {
//            _getCount isNull {
//                _Exception("GetCount(getcount: ()-> Int)")
//            }
//            count = _getCount!!()
//        }
        _getCount.isNull {
            count = filterData.size
        }
        _getCount.isNotNull {
            count = _getCount!!()
        }
        return count
    }

    private fun _Exception(message: String)
    {
        throw Exception("خاتالىق يۈز بەردى، بەزى فۇنكىسىيەلەرنى چوقۇم ئىشلىتىپ ئۇچۇرلارنى تولۇق تەمىنلىشىڭىز كىرەك ياكى \n\ndata\n\nارامىتىرىغا قىممەت بىرىپ ئىشلىتىدىغان سانلىق مەلۇماتنى دەسلەپلەشتۈرۈشىڭىز كىرەك،\n\nنۆۋەتتىكى ئەمەلگە ئاشۇرۇلمىغان فۇنكىسىيە:\n\n$message")
    }

}

fun <T> createBaseAdapter(context: Context, layout_res_id: Int, data: ArrayList<T>, constructor: BaseAdapter<T>.() -> Unit) : BaseAdapter<T>
{
    val temp = BaseAdapter(context, layout_res_id, data)
    temp.constructor()
    return temp
}